package pl.mchaniewski.ryneczek.services.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import pl.mchaniewski.ryneczek.dao.UserDao;
import pl.mchaniewski.ryneczek.pojo.User;
import pl.mchaniewski.ryneczek.services.UserService;
import pl.mchaniewski.ryneczek.utilities.DateUtil;

@Service("userService")
public class UserServiceImpl implements UserService, UserDetailsService {
    private static final Logger logger = LoggerFactory
            .getLogger(UserServiceImpl.class);
    private UserDao userDao;

    @Autowired
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public User findById(Integer id) {
        try {
            return userDao.findById(id);
        } catch (Exception ex) {
            logger.error("Exception: {}", ex.getMessage());

            return null;
        }
    }

    @Override
    public User save(User entity) {
        try {
            return userDao.save(entity);
        } catch (Exception ex) {
            logger.error("Exception: {}", ex.getMessage());

            return null;
        }
    }

    @Override
    public boolean remove(User entity) {
        try {
            userDao.remove(entity);
        } catch (Exception ex) {
            logger.error("Exception: {}", ex.getMessage());

            return false;
        }

        return true;
    }

    @Override
    public List<User> findAll() {
        try {
            return userDao.loadAll();
        } catch (Exception ex) {
            logger.error("Exception: {}", ex.getMessage());

            return null;
        }
    }

    @Override
    public User findByLogin(String username) {
        List<User> userList;
        try {
            userList = userDao.findByLogin(username);
        } catch (Exception ex) {
            logger.error("Exception: {}", ex.getMessage());

            return null;
        }

        if (userList == null || userList.size() == 0) {
            return null;
        }

        if (userList.size() > 1) {
            logger.warn("Two or more user with same login! Login: {}", userList
                    .get(0).getLogin());
        }

        return userList.get(0);
    }

    @Override
    public User createNewUser(String login, String password) {
        User newUser = new User();
        newUser.setLogin(login);
        newUser.setPass(password);
        newUser.setCreateDate(DateUtil.getNow());
        newUser.setFlags(User.DEFAULT_FLAGS);
        newUser.setIdentityNumber(null);

        return save(newUser);
    }

    @Override
    public User changePassword(User user, String newPassword) {
        user.setPass(newPassword);

        return save(user);
    }

    @Override
    public User changeLoginAndPassword(User user, String newLogin,
            String newPassword) {
        user.setLogin(newLogin);
        user.setPass(newPassword);

        return save(user);
    }

    @Override
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException, DataAccessException {
        User user = findByLogin(username);
        if (user == null) {
            throw new UsernameNotFoundException(null);
        }

        if (logger.isDebugEnabled()) {
            logger.debug("User {} is requested.", username);
        }

        String login = user.getLogin();
        String password = user.getPass();
        boolean enabled = user.isActive();
        boolean accountNonExpired = user.isActive();
        boolean credentialsNonExpired = user.isActive();
        boolean accountNonLocked = user.isActive();

        Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        for (String role : user.getRoles()) {
            authorities.add(new GrantedAuthorityImpl(role));
        }

        org.springframework.security.core.userdetails.User springUser = new org.springframework.security.core.userdetails.User(
                login, password, enabled, accountNonExpired,
                credentialsNonExpired, accountNonLocked, authorities);

        return springUser;
    }

}
